/*
    Invtro for Inércia Demoparty 2010

    http://creativecommons.org/licenses/by-nc-sa/2.5/
    
    Victor Martins
    www.pixelnerve.com
    
    Handle the line particles in the background
*/

import java.nio.*;
import vitamin.utils.BufferUtils;



  class ParticleComparator implements Comparator
  {
    public final int compare( Object a, Object b )
    {
       float z1 = ((Particle)a)._pos.z;
       float z2 = ((Particle)b)._pos.z;
  
      if( z1 > z2 )  return 1;
      else return -1;
    }
  } 



class ParticleSystem
{
    int MAX_PARTICLES = 175;

    ParticleSystem( ArrayList paths )
    {
//        _paths = paths;

        _positionBuffer = BufferUtils.createFloatBuffer( MAX_PARTICLES*3*2 );
        _colorBuffer = BufferUtils.createFloatBuffer( MAX_PARTICLES*4*2 );
/*        _vboID = new int[1];
        vgl.gl().glGenBuffersARB( 1, _vboID, 0 );
        vgl.gl().glBindBufferARB( GL.GL_ARRAY_BUFFER_ARB, _vboID[0] );
        vgl.gl().glBufferDataARB( GL.GL_ARRAY_BUFFER_ARB, xyz.length, vertexBuffer, GL.GL_STREAM_DRAW_ARB );
        vgl.gl().glBindBufferARB( GL.GL_ARRAY_BUFFER_ARB, 0 ); 
*/

        _particleCount = 0;
        _particleList = new ArrayList();
        
        _comparator = new ParticleComparator();
        
        
        particleAddTime = 0.5;
        particleCountTime = 0;
        

        _emitter = new Vector3();
    }
    
    
    void init()
    {
    }


    void render()
    {
        renderVA();
//        renderImmediateMode();
    }



    void renderVA()
    {
        vgl.enableTexture( false );
        updateBuffers();
        renderBuffers();
    }


    void renderImmediateMode()
    {
        vgl.enableTexture( false );

        vgl.beginShape( VGL.LINES );
        for( int i=0; i<_particleList.size(); i++ )
        {
            Particle p = (Particle)_particleList.get( i );
            if( p._pos != null )
            {
                //
                // Draw a line for particle
                //
                vgl.color4( p._color.r, p._color.g, p._color.b, p._color.a );
                vgl.vertex( p._origin.x, p._origin.y, p._origin.z );
//                vgl.color4( p._color.r, p._color.g, p._color.b, 0 );
                vgl.vertex( p._pos.x, p._pos.y, p._pos.z );
            }
        }
        vgl.endShape();     
    }
    
    

    void update( float time )
    {
        _emitter.set( sin(time*0.52)*200, -200, 0 );
        _emitter.x += 250 * (2*noise( time*0.001, time * 0.001+_emitter.x*0.003, _emitter.y*0.0001 )-1);
//        _emitter.y += 100 * (2*noise( time * 0.001, +_emitter.z*0.003, time*0.1 )-1);
//        _emitter.z += 145 * (2*noise( time*0.001, time * 0.01 +_emitter.z*0.0003 )-1);
//        _emitter = ((Path)_paths.get(0)).getPointOnPath( time*8 );
        
        
        //
        // Add more particles until it reaches MAX count
        //
        if( (time-particleCountTime) > particleAddTime && _particleList.size() < MAX_PARTICLES )
        {
            particleCountTime = time;

/*            int rnd = (int)random(_paths.size() );
            Particle p = new Particle( _particleCount, (Path)_paths.get(rnd), random(6, 10) );
            _particleList.add( p );
*/

            float off = 50;
            Vector3 offtmp = new Vector3( random(-off, off), random(-off, off), random(-off, off) );
            Vector3 tmp = Vector3.add( _emitter, offtmp );
            
            int amount = (int)random(1, 4);
            for( int ii=0; ii<amount; ii++ )
            {                
                Particle p = new Particle( _particleCount, tmp, random(3, 10) );
                _particleList.add( p );
                _particleCount++;
            }
        }
        while( _particleList.size() > MAX_PARTICLES )
        {
            _particleList.remove( _particleList.size()-1 );
        }


        //
        // Update particles
        //
        for( int i=0; i<_particleList.size(); i++ )
        {
            Particle p = (Particle)_particleList.get( i );
            p.update( time );

            if( p.isDead() )
            {
                _particleList.remove( p );
/*                
//                int rnd = (int)random(_paths.size() );
//                p.reset( (Path)_paths.get(rnd), random(14, 30) );
                p.reset( _emitter, random(13, 20) );
                
                if( random(100) > 50 )
                {
                    int amount = (int)random(1, 5 );
                    for( int ii=0; ii<amount; ii++ )
                    {
                        Particle pp = (Particle)_particleList.get( ii );
                        pp.reset( _emitter, random(13, 20) );
                    }
                }
*/
            }
        }
        
        
        //
        // Sort particles
        //
        Collections.sort( _particleList, _comparator );  
    }


    void renderBuffers()
    {
        vgl.gl().glEnableClientState( GL.GL_VERTEX_ARRAY );
        vgl.gl().glEnableClientState( GL.GL_COLOR_ARRAY );
        vgl.gl().glVertexPointer( 3, GL.GL_FLOAT, 0, _positionBuffer );
        vgl.gl().glColorPointer( 4, GL.GL_FLOAT, 0, _colorBuffer );

        vgl.gl().glDrawArrays( GL.GL_LINES, 0, _particleList.size()*2 );

        vgl.gl().glDisableClientState( GL.GL_VERTEX_ARRAY );
        vgl.gl().glDisableClientState( GL.GL_COLOR_ARRAY );
    }


    void updateBuffers()
    {
        _positionBuffer.clear();
        _colorBuffer.clear();
        
        int pi = 0;
        int ci = 0;
        for( int i=0; i<_particleList.size(); i++ )
        {
            Particle p = (Particle)_particleList.get( i );

            Color4 c = p._color;
            Vector3 v0 = p._origin;
            Vector3 v1 = p._pos;
            
            // positions
            _positionBuffer.put( pi++, v0.x );
            _positionBuffer.put( pi++, v0.y );
            _positionBuffer.put( pi++, v0.z );
            _positionBuffer.put( pi++, v1.x );
            _positionBuffer.put( pi++, v1.y );
            _positionBuffer.put( pi++, v1.z );
            // colors
            _colorBuffer.put( ci++, c.r );
            _colorBuffer.put( ci++, c.g );
            _colorBuffer.put( ci++, c.b );
            _colorBuffer.put( ci++, c.a );
            _colorBuffer.put( ci++, c.r );
            _colorBuffer.put( ci++, c.g );
            _colorBuffer.put( ci++, c.b );
            _colorBuffer.put( ci++, c.a );
        }

        _positionBuffer.rewind();
        _colorBuffer.rewind();
    }



    //
    // Members
    //
    
//    ArrayList _paths;

    float particleAddTime;
    float particleCountTime;
    
    Vector3 _emitter;
    
    int _particleCount;
    ArrayList _particleList;
    
    ParticleComparator _comparator;
    
    int[] _vboID; 
    FloatBuffer _positionBuffer;
    FloatBuffer _colorBuffer;
}
